# !/usr/bin/env python
# -*- coding: UTF-8 -*-

''' 用于生成二维码数字'''

import base64
import hashlib
import hmac
import string
import struct
import time
from io import BytesIO

import qrcode
import qrcode_terminal
from django.utils.crypto import get_random_string

# from django.utils.crypto import get_random_string


# 获取新的secret
def get_secret(length=10) -> str:
    '''da'''
    return base64.b32encode(
        get_random_string(
            length=length,
            allowed_chars=string.ascii_letters + string.digits
        ).encode()
    ).decode()


# 生产二维码url
def get_auth_url(user_id, secret, issuer='main'):
    url_template = 'otpauth://totp/{isr}:{uid}?secret={secret}&issuer={isr}'
    return url_template.format(
        uid=user_id,
        secret=secret,
        isr=issuer)


# 将二维码转译成base64-text 格式,然后通过前端转译
def get_image_b64(url):
    qrcode_terminal.draw(url)
    qr = qrcode.make(url)
    img = BytesIO()
    qr.save(img)
    return base64.b64encode(img.getvalue()).decode()


# 基于google的源码校验
# https://en.wikipedia.org/wiki/Google_Authenticator
# 源码
# ######################
# function GoogleAuthenticatorCode(string secret)
#       key := 5B5E7MMX344QRHYO
#       message := floor(current Unix time / 30)
#       hash := HMAC-SHA1(key, message)
#       offset := last nibble of hash
#       truncatedHash := hash[offset..offset+3]  //4 bytes starting at the offset
#       Set the first bit of truncatedHash to zero  //remove the most significant bit
#       code := truncatedHash mod 1000000
#       pad code with 0 from the left until length of code is 6
#       return code
#######################
def get_hotp_token(secret, intervals_no):
    key = base64.b32decode(secret, True)
    msg = struct.pack(">Q", intervals_no)
    hash_set = hmac.new(key, msg, hashlib.sha1).digest()
    offset = ord(chr(hash_set[19])) & 15
    token = (struct.unpack(
        ">I", hash_set[offset:offset + 4])[0] & 0x7fffffff) % 1000000
    return str(token).zfill(6)


# 输入secret,校验secret
def get_totp_token(secret):
    return get_hotp_token(secret, intervals_no=int(time.time()) // 30)


def verify(code, secret):
    result = get_totp_token(secret)
    if str(code) == str(result):
        return True
    else:
        return False
